feat(core): add HoverController#6358
Conversation
🦋 Changeset detectedLatest commit: 253392d The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📚 Branch Preview Links🔍 First Generation Visual Regression Test ResultsWhen a visual regression test fails (or has previously failed while working on this branch), its results can be found in the following URLs:
Deployed to Azure Blob Storage: If the changes are expected, update the |
Rajdeepc
left a comment
There was a problem hiding this comment.
I like how you have created the pointer bridge and keyboard focus. Some feedbacks on optimizations. Overall looks excellent.
… into seckles/hover-controller
Rajdeepc
left a comment
There was a problem hiding this comment.
Nice! A couple of questions/feedback you can do post merge too.
- non-default closeDelay value don't have a test case. Can you please add a test with an explicit non-default closeDelay to prove the property flows through end-to-end.
- Is closeDelay intended to be exposed as an attribute on consuming components (e.g. ) or remain an internal implementation detail?
blunteshwar
left a comment
There was a problem hiding this comment.
nit: Do you feel we need a changeset here?
Description
Adds
HoverController, a LitReactiveControllerthat centralises hover and keyboard-focus event wiring for 2nd-gen components that use the native Popover API (Tooltip, and any future popover-adjacent component).What it provides
delayms; leaving starts a matching cooldown.delay="0"opens and closes synchronously.Tabfocus opens immediately and suppresses all pointer-driven timers untilfocusout.popover="auto"fires a light dismiss onpointerdown(the trigger is outside the popover surface); opening on the subsequentfocusinwould cause a visible flash. The controller detects this event sequence and skips the open.disabled/manualguards — re-evaluated live on every host update, no page reload required.Basic usage
Method
setTarget(trigger: HTMLElement | null)updated()whenever the resolved trigger changes. Passingnulldetaches all listeners.Constructor options
warmStateKeystringdocument. Use the element tag name (e.g.'swc-tooltip'). Must be static.HoverControllerHostinterfacedelaynumber0= immediate.manualbooleantrue, controller skips all event wiring.disabledbooleantrue, controller skips all event wiring.showPopover()hidePopover()The controller does not resolve trigger elements, set ARIA attributes, or dispatch lifecycle events — those remain the consuming component's responsibility.
Motivation and context
Tooltip, and any future component that uses
popover="auto", requires identical hover/focus logic. Extracting it into a shared controller keeps that logic in one place and tested independently before any consuming component is built.Related issue(s)
Author's checklist
Reviewer's checklist
Manual review test cases
Warm-up and cooldown
WCAG 1.4.13 pointer bridge
Keyboard focus
Pointer-click focus does not open
delay=1500Device review
Accessibility testing checklist
Keyboard (required — document steps below)
Screen reader (required — document steps below)
HoverControllerdoes not set ARIA attributes directly; consuming components (e.g. Tooltip) are responsible for wiringaria-describedbyand roles